package middleware

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/Unknwon/goconfig"
	"github.com/gin-gonic/gin"
)

//Result validate返回对象
type Result struct {
	ID    int    `json:"id"`
	Msg   string `json:"msg"`
	User  string `json:"user"`
	Token string `json:"token"`
}

//SSOMiddleware 统一认证中间件,通过的放行，不通过的跳到SSO进行登录
func SSOMiddleware(c *gin.Context) {

	cfg, err := goconfig.LoadConfigFile("./conf/app.ini")
	if err != nil {
		panic(err)
	}
	//SsoURL sso地址
	SsoURL, err := cfg.GetValue("s-iam", "ssourl")
	if err != nil {
		panic(err)
	}

	//第一步，先从cookies里面获取token
	siamToken, err := c.Cookie("SiamToken")
	//情况1： cookie无token
	if err != nil || siamToken == "" {
		if err != nil {
			fmt.Println(err.Error())
		}
		//1.1 是否是试用令牌访问
		//查询是否带ticket
		ticket := c.Query("ticket")

		//无ticket 无cookie 直接跳转到sso auth页面进行验证是否已经登录
		if ticket == "" {
			c.Abort()
			c.Redirect(http.StatusFound, SsoURL+"/sso/auth"+"?redirect_uri=http://"+c.Request.Host)
			return
		}

		//无token 的情况 进行验证ticket
		result, err := validate(SsoURL, ticket)
		//ticket 验证失败
		if err != nil {
			c.JSON(501, err)
			setCookie(c, Result{User: "",
				Token: ""}, c.Request.URL.Hostname())
			c.Abort()
			return
		}
		setCookie(c, result, c.Request.Host)
		c.Redirect(http.StatusFound, "http://"+c.Request.Host)
		c.Abort()
		return
	}

	//第二步，若cookie有token，验证token
	result, err := validate(SsoURL, siamToken)
	if err != nil || result.Token == "" || result.User == "" {
		setCookie(c, Result{User: "", Token: ""}, c.Request.Host)
		c.Redirect(http.StatusFound, SsoURL+"/sso/auth"+"?redirect_uri=http://"+c.Request.Host)
		c.Abort()
		return
	}
	c.Set("user", result.User)
	c.Next()
}

//验证token的合法性
func validate(url string, token string) (Result, error) {
	url = url + "/" + "validate" + "?" + "token=" + token
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("验证接口请求错误，请检查")
		return Result{}, err
	}
	//defer resp.Body.Close()
	//data, _ := ioutil.ReadAll(resp.Body)

	result := Result{}
	//json.Unmarshal(data, &result)
	json.NewDecoder(resp.Body).Decode(&result)
	defer resp.Body.Close()
	return result, nil
}

//封装cookies方法
func setCookie(c *gin.Context, r Result, host string) {
	//设置token
	c.SetCookie("SiamToken", r.Token, 3600, "/", host, false, true)
}

//todo  tcp 长连接 测试
// func validate2(url string, token string) (Result, error) {
// 	url = url + "/" + "validate" + "?" + "token=" + token
// 	client := &http.Client{}
// 	req, _ := http.NewRequest("GET", url, nil)
// 	req.Header.Add("Connection", "Keep-Alive")
// 	//发起请求
// 	reps, err := client.Do(req)
// 	if err != nil {
// 		fmt.Println(err.Error())
// 		return Result{},err
// 	}

// 	data:=ioutil

// 	return

// }
